package com.zenithmind.exam.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.annotation.DataCache;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.exam.mapper.QuestionMapper;
import com.zenithmind.exam.pojo.dto.QuestionCreateDTO;
import com.zenithmind.exam.pojo.entity.Question;
import com.zenithmind.exam.pojo.vo.QuestionVO;
import com.zenithmind.exam.service.QuestionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 题目服务实现类
 * 
 * @author ZenithMind
 * @since 2024-07-01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements QuestionService {

    private final QuestionMapper questionMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createQuestion(QuestionCreateDTO questionCreateDTO) {
        try {
            Question question = new Question();
            BeanUtils.copyProperties(questionCreateDTO, question);
            
            // 转换选项和答案为JSON格式
            if (!CollectionUtils.isEmpty(questionCreateDTO.getOptions())) {
                question.setOptions(JSON.toJSONString(questionCreateDTO.getOptions()));
            }
            question.setCorrectAnswer(JSON.toJSONString(questionCreateDTO.getCorrectAnswer()));
            
            // 转换标签为JSON格式
            if (!CollectionUtils.isEmpty(questionCreateDTO.getTags())) {
                question.setTags(JSON.toJSONString(questionCreateDTO.getTags()));
            }
            
            // 转换图片URLs为JSON格式
            if (!CollectionUtils.isEmpty(questionCreateDTO.getImageUrls())) {
                question.setImageUrls(JSON.toJSONString(questionCreateDTO.getImageUrls()));
            }
            
            // 转换附件URLs为JSON格式
            if (!CollectionUtils.isEmpty(questionCreateDTO.getAttachmentUrls())) {
                question.setAttachmentUrls(JSON.toJSONString(questionCreateDTO.getAttachmentUrls()));
            }
            
            // 设置默认值
            if (question.getDifficulty() == null) {
                question.setDifficulty(2); // 默认中等难度
            }
            if (question.getScore() == null) {
                question.setScore(getDefaultScore(question.getType()));
            }
            if (question.getStatus() == null) {
                question.setStatus(1); // 默认启用
            }
            
            // 初始化统计字段
            question.setUseCount(0L);
            question.setCorrectCount(0L);
            question.setCorrectRate(java.math.BigDecimal.ZERO);

            boolean result = save(question);
            if (result) {
                log.info("创建题目成功，题目ID: {}, 题目标题: {}", question.getId(), question.getTitle());
                // 更新题库题目数量
                try {
                    // 注意：这里需要根据实际的QuestionBankService来实现
                    // questionBankService.updateQuestionCount(question.getBankId());
                    log.info("需要更新题库题目数量，题库ID: {}", question.getBankId());
                } catch (Exception e) {
                    log.warn("更新题库题目数量失败，题库ID: {}", question.getBankId(), e);
                }
            }
            return result;
        } catch (Exception e) {
            log.error("创建题目失败", e);
            throw new BusinessException("创建题目失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateQuestion(String questionId, QuestionCreateDTO questionCreateDTO) {
        try {
            Question existingQuestion = getById(questionId);
            if (existingQuestion == null) {
                throw new BusinessException("题目不存在");
            }

            Question question = new Question();
            BeanUtils.copyProperties(questionCreateDTO, question);
            question.setId(questionId);
            
            // 转换选项和答案为JSON格式
            if (!CollectionUtils.isEmpty(questionCreateDTO.getOptions())) {
                question.setOptions(JSON.toJSONString(questionCreateDTO.getOptions()));
            }
            question.setCorrectAnswer(JSON.toJSONString(questionCreateDTO.getCorrectAnswer()));
            
            // 转换标签为JSON格式
            if (!CollectionUtils.isEmpty(questionCreateDTO.getTags())) {
                question.setTags(JSON.toJSONString(questionCreateDTO.getTags()));
            }
            
            // 转换图片URLs为JSON格式
            if (!CollectionUtils.isEmpty(questionCreateDTO.getImageUrls())) {
                question.setImageUrls(JSON.toJSONString(questionCreateDTO.getImageUrls()));
            }
            
            // 转换附件URLs为JSON格式
            if (!CollectionUtils.isEmpty(questionCreateDTO.getAttachmentUrls())) {
                question.setAttachmentUrls(JSON.toJSONString(questionCreateDTO.getAttachmentUrls()));
            }

            boolean result = updateById(question);
            if (result) {
                log.info("更新题目成功，题目ID: {}, 题目标题: {}", questionId, question.getTitle());
            }
            return result;
        } catch (Exception e) {
            log.error("更新题目失败", e);
            throw new BusinessException("更新题目失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteQuestion(String questionId) {
        try {
            // 检查题目是否被考试使用
            try {
                // 注意：这里需要根据实际的ExamQuestionRel实体和Mapper来实现
                // LambdaQueryWrapper<ExamQuestionRel> queryWrapper = new LambdaQueryWrapper<>();
                // queryWrapper.eq(ExamQuestionRel::getQuestionId, questionId);
                // long count = examQuestionRelMapper.selectCount(queryWrapper);
                // if (count > 0) {
                //     log.warn("题目被考试使用，无法删除，题目ID: {}", questionId);
                //     throw new BusinessException("题目被考试使用，无法删除");
                // }
                log.info("检查题目使用情况，题目ID: {}", questionId);
            } catch (Exception e) {
                log.error("检查题目使用情况失败，题目ID: {}", questionId, e);
                throw new BusinessException("检查题目使用情况失败: " + e.getMessage());
            }

            // 获取题目信息（用于后续更新题库数量）
            Question question = getById(questionId);
            String bankId = question != null ? question.getBankId() : null;

            boolean result = removeById(questionId);
            if (result) {
                log.info("删除题目成功，题目ID: {}", questionId);

                // 更新题库题目数量
                if (bankId != null) {
                    try {
                        // 注意：这里需要根据实际的QuestionBankService来实现
                        // questionBankService.updateQuestionCount(bankId);
                        log.info("需要更新题库题目数量，题库ID: {}", bankId);
                    } catch (Exception e) {
                        log.warn("更新题库题目数量失败，题库ID: {}", bankId, e);
                    }
                }
            }
            return result;
        } catch (Exception e) {
            log.error("删除题目失败", e);
            throw new BusinessException("删除题目失败: " + e.getMessage());
        }
    }

    @Override
    @DataCache(key = "exam:question:#{questionId}:#{showAnswer}", expireTime = 15, timeUnit = TimeUnit.MINUTES)
    public QuestionVO getQuestionById(String questionId, boolean showAnswer) {
        Question question = getById(questionId);
        if (question == null) {
            return null;
        }
        return convertToVO(question, showAnswer);
    }

    @Override
    public List<QuestionVO> getQuestionsByBankId(String bankId) {
        List<Question> questions = questionMapper.selectByBankId(bankId);
        return questions.stream()
                .map(question -> convertToVO(question, false))
                .collect(Collectors.toList());
    }

    @Override
    public IPage<QuestionVO> getQuestionPage(Page<Question> page, String bankId, String title, 
                                           Integer type, Integer difficulty, Integer status) {
        IPage<Question> questionPage = questionMapper.selectQuestionPage(page, bankId, title, type, difficulty, status);
        
        IPage<QuestionVO> voPage = new Page<>();
        BeanUtils.copyProperties(questionPage, voPage);
        
        List<QuestionVO> voList = questionPage.getRecords().stream()
                .map(question -> convertToVO(question, false))
                .collect(Collectors.toList());
        voPage.setRecords(voList);
        
        return voPage;
    }

    @Override
    public List<QuestionVO> getRandomQuestions(String bankId, Integer type, Integer difficulty, Integer count) {
        List<Question> questions = questionMapper.selectRandomQuestions(bankId, type, difficulty, count);
        return questions.stream()
                .map(question -> convertToVO(question, false))
                .collect(Collectors.toList());
    }

    @Override
    public List<QuestionVO> searchQuestions(String keyword) {
        List<Question> questions = questionMapper.searchQuestions(keyword);
        return questions.stream()
                .map(question -> convertToVO(question, false))
                .collect(Collectors.toList());
    }

    @Override
    public List<QuestionVO> getQuestionsByTag(String tag) {
        List<Question> questions = questionMapper.selectByTag(tag);
        return questions.stream()
                .map(question -> convertToVO(question, false))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateQuestionStatus(String questionId, Integer status) {
        try {
            Question question = new Question();
            question.setId(questionId);
            question.setStatus(status);
            
            boolean result = updateById(question);
            if (result) {
                log.info("更新题目状态成功，题目ID: {}, 状态: {}", questionId, status);
            }
            return result;
        } catch (Exception e) {
            log.error("更新题目状态失败", e);
            throw new BusinessException("更新题目状态失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchDeleteQuestions(List<String> questionIds) {
        try {
            boolean result = removeByIds(questionIds);
            if (result) {
                log.info("批量删除题目成功，题目数量: {}", questionIds.size());
            }
            return result;
        } catch (Exception e) {
            log.error("批量删除题目失败", e);
            throw new BusinessException("批量删除题目失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean copyQuestionToBank(String questionId, String targetBankId) {
        try {
            Question sourceQuestion = getById(questionId);
            if (sourceQuestion == null) {
                throw new BusinessException("源题目不存在");
            }

            Question newQuestion = new Question();
            BeanUtils.copyProperties(sourceQuestion, newQuestion);
            newQuestion.setId(null); // 清空ID，让系统自动生成
            newQuestion.setBankId(targetBankId);
            newQuestion.setUseCount(0L);
            newQuestion.setCorrectCount(0L);
            newQuestion.setCorrectRate(java.math.BigDecimal.ZERO);

            boolean result = save(newQuestion);
            if (result) {
                log.info("复制题目成功，源题目ID: {}, 新题目ID: {}", questionId, newQuestion.getId());
            }
            return result;
        } catch (Exception e) {
            log.error("复制题目失败", e);
            throw new BusinessException("复制题目失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean moveQuestionToBank(String questionId, String targetBankId) {
        try {
            Question question = new Question();
            question.setId(questionId);
            question.setBankId(targetBankId);
            
            boolean result = updateById(question);
            if (result) {
                log.info("移动题目成功，题目ID: {}, 目标题库ID: {}", questionId, targetBankId);
            }
            return result;
        } catch (Exception e) {
            log.error("移动题目失败", e);
            throw new BusinessException("移动题目失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateQuestionStatistics(String questionId, boolean isCorrect) {
        try {
            // 更新使用次数
            questionMapper.incrementUseCount(questionId);
            
            // 如果答对了，更新正确次数
            if (isCorrect) {
                questionMapper.incrementCorrectCount(questionId);
            }
            
            // 更新正确率
            questionMapper.updateCorrectRate(questionId);
            
            log.debug("更新题目统计成功，题目ID: {}, 是否正确: {}", questionId, isCorrect);
        } catch (Exception e) {
            log.error("更新题目统计失败", e);
        }
    }

    @Override
    public List<QuestionVO> getFrequentWrongQuestions(Integer limit) {
        List<Question> questions = questionMapper.selectFrequentWrongQuestions(limit);
        return questions.stream()
                .map(question -> convertToVO(question, false))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean importQuestions(String bankId, List<QuestionCreateDTO> questions) {
        try {
            for (QuestionCreateDTO questionDTO : questions) {
                questionDTO.setBankId(bankId);
                createQuestion(questionDTO);
            }
            log.info("导入题目成功，题库ID: {}, 题目数量: {}", bankId, questions.size());
            return true;
        } catch (Exception e) {
            log.error("导入题目失败", e);
            throw new BusinessException("导入题目失败: " + e.getMessage());
        }
    }

    @Override
    public List<QuestionVO> exportQuestions(String bankId) {
        List<Question> questions = questionMapper.selectByBankId(bankId);
        return questions.stream()
                .map(question -> convertToVO(question, true))
                .collect(Collectors.toList());
    }

    /**
     * 转换为VO对象
     */
    private QuestionVO convertToVO(Question question, boolean showAnswer) {
        QuestionVO vo = new QuestionVO();
        BeanUtils.copyProperties(question, vo);
        
        // 转换JSON字段
        if (question.getOptions() != null) {
            vo.setOptions(JSON.parseArray(question.getOptions(), String.class));
        }
        
        if (showAnswer && question.getCorrectAnswer() != null) {
            vo.setCorrectAnswer(JSON.parseArray(question.getCorrectAnswer(), String.class));
        }
        
        if (question.getTags() != null) {
            vo.setTags(JSON.parseArray(question.getTags(), String.class));
        }
        
        if (question.getImageUrls() != null) {
            vo.setImageUrls(JSON.parseArray(question.getImageUrls(), String.class));
        }
        
        if (question.getAttachmentUrls() != null) {
            vo.setAttachmentUrls(JSON.parseArray(question.getAttachmentUrls(), String.class));
        }
        
        // 设置类型名称
        vo.setTypeName(getQuestionTypeName(question.getType()));
        
        // 设置难度名称
        vo.setDifficultyName(getDifficultyName(question.getDifficulty()));
        
        // 设置状态名称
        vo.setStatusName(getStatusName(question.getStatus()));
        
        return vo;
    }

    /**
     * 获取默认分值
     */
    private Integer getDefaultScore(Integer type) {
        switch (type) {
            case 1: // 单选题
                return 2;
            case 2: // 多选题
                return 3;
            case 3: // 填空题
                return 3;
            case 4: // 简答题
                return 10;
            case 5: // 判断题
                return 2;
            default:
                return 2;
        }
    }

    /**
     * 获取题目类型名称
     */
    private String getQuestionTypeName(Integer type) {
        switch (type) {
            case 1: return "单选题";
            case 2: return "多选题";
            case 3: return "填空题";
            case 4: return "简答题";
            case 5: return "判断题";
            default: return "未知";
        }
    }

    /**
     * 获取难度名称
     */
    private String getDifficultyName(Integer difficulty) {
        switch (difficulty) {
            case 1: return "简单";
            case 2: return "中等";
            case 3: return "困难";
            default: return "未知";
        }
    }

    /**
     * 获取状态名称
     */
    private String getStatusName(Integer status) {
        switch (status) {
            case 0: return "禁用";
            case 1: return "启用";
            case 2: return "审核中";
            default: return "未知";
        }
    }
}
